﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Win32;
using System.IO;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using VIA.Foundation;
using VIA.ImageProcessing;
using VIA.Integration;
using VIA.Integration.Domain;
using VIA.Integration.Presentation;
using VIA.Presentation;
using VIA.Presentation.Contracts;
using VIA.Presentation.View;
using VIA.Project.Domain.Devices;

namespace VIA.Project.Presentation.ViewModel.Inspection
{
    [ViewModel(typeof(IVirtualCameraEditorView))]
    public class VirtualCameraEditorViewModel : EditorViewModel<IVirtualCameraEditorView, VirtualCameraOption>
    {
        #region Fields
        protected IMessageService _messageService;
        protected IBusyService _busyService;
        protected IDispatcherService _dispatcherService;
        protected IShellService _shellService;
        protected IFileDialogService _dialogService;
        protected ILogger _logger;
        private IVirtualCamera _camera;
        private WriteableBitmap _luminanceImageSource;
        private ImageData3DU imageData3DU;

        #endregion

        #region Commands

        public IRelayCommand BrowseCommand { get; }
        public IRelayCommand SaveAndCloseCommand { get; }
        public IRelayCommand CloseCommand { get; }
        public IRelayCommand SnapCommand { get; }
        #endregion

        #region Properties


        public IVirtualCamera Camera
        {
            get
            {
                return _camera;
            }
            set
            {
                if (_camera != null) _camera.ImageObjectReceived -= Camera_ImageReceived;
                if (SetProperty(ref _camera, value))
                {
                    _camera.ImageObjectReceived += Camera_ImageReceived;
                    _camera.Option = Option;
                    _dispatcherService.InvokeAsync(() => _commandFactory.RaiseCanExecuteChanged());
                }
            }
        }

        public WriteableBitmap LuminanceImageSource
        {
            get => _luminanceImageSource;
            set => SetProperty(ref _luminanceImageSource, value);
        }

        public ImageData3DU ImageData3DU
        {
            get => imageData3DU;
            set => SetProperty(ref imageData3DU, value);
        }

        #endregion

        #region Constructor
        public VirtualCameraEditorViewModel(IServiceProvider service) : base(service)
        {
            _messageService = service.GetService<IMessageService>();
            _busyService = service.GetService<IBusyService>();
            _dispatcherService = service.GetService<IDispatcherService>();
            _shellService = service.GetService<IShellService>();
            _dialogService = service.GetService<IFileDialogService>();
            _logger = service.GetService<ILogger<VirtualCameraEditorViewModel>>();
            BrowseCommand = _commandFactory.Create(Browse);
            SaveAndCloseCommand = _commandFactory.Create(SaveAndClose);
            CloseCommand = _commandFactory.Create(Close);
            SnapCommand = _commandFactory.Create(Snap);
        }

        #endregion

        #region CommandHandles


        private void Camera_ImageReceived(object? sender, object e)
        {
            WriteableBitmap writeableBitmap = null;
            ImageData3DU depth = null;
            if (e is ImageData imageData)
            {
                writeableBitmap = imageData.ToWriteableBitmap();
            }
            else if (e is ProfileImage profileImage)
            {
                writeableBitmap = profileImage.Luminance.ToWriteableBitmap();
                depth = profileImage.Depth;
            }
            _dispatcherService.Invoke(() =>
            {
                LuminanceImageSource = writeableBitmap;
                ImageData3DU = depth;
            });

        }

        async Task SaveAndClose()
        {
            await Save();
            Close();
        }

        private void Close()
        {
            try
            {
                View.Close();

            }
            catch (Exception)
            {
            }
        }

        async Task Snap()
        {
            try
            {
                Camera.Snap();
            }
            catch (Exception ex)
            {
                _messageService.ShowError(View, $"相机{Camera.Id}触发失败:{ex}");
                _logger.LogError($"相机{Camera.Id}触发失败:{ex}");
            }
        }

        void Browse()
        {
            try
            {
                string str = string.Empty;
                if (!Option.IsUseImageFolder)
                {
                    OpenFileDialog dialog = new OpenFileDialog();
                    if (Option != null && !Option.ImagePath.IsNullOrEmpty())
                    {
                        FileInfo fileInfo = new FileInfo(Option.ImagePath);
                        DirectoryInfo directory = fileInfo.Directory;
                        if (directory.Exists)
                        {
                            dialog.InitialDirectory = directory.FullName;
                        }
                    }
                    dialog.Title = "选择文件路径";
                    dialog.DefaultExt = "*.*";
                    dialog.Filter = "所有文件|*.*|BMP|*.bmp|TIF|*.tif|PNG|*.png|JPG|*.jpg";
                    if (dialog.ShowDialog(_shellService.ShellWindow) == true)
                    {
                        str = dialog.FileName;
                    }
                }
                else
                {
                    str = _dialogService.ShowFolderBrowserDialog(_shellService.ShellWindow);
                }
                if (!str.IsNullOrEmpty())
                {
                    Option.ImagePath = str;
                }
            }
            catch (Exception e)
            {
                _messageService.ShowError(View, e);
            }

        }

        private async void View_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (Camera != null)
            {
                Camera.ImageObjectReceived -= Camera_ImageReceived;
            }
            await SaveAndClose();
        }
        protected override void OnAttach()
        {
            View.Closing += View_Closing;
            base.OnAttach();
        }

        protected override void OnEditObjectChanged(IObject oldObject, IObject newObject)
        {
            if (newObject is IVirtualCamera camera)
                Camera = camera;
        }

        #endregion
    }
}
